/*
 * @(#) $Header$
 *
 * Copyright (C) 2007  Forklabs Daniel Léonard
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package ca.forklabs.media.jai.operator;

import java.awt.RenderingHints;
import java.awt.image.DataBuffer;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.util.Collection;
import javax.media.jai.JAI;
import javax.media.jai.OperationDescriptor;
import javax.media.jai.OperationDescriptorImpl;
import javax.media.jai.ParameterBlockJAI;
import javax.media.jai.registry.CollectionRegistryMode;
import javax.media.jai.util.Range;
import ca.forklabs.media.jai.ImageFunction3D;

/**
 * Class {@code ImageFunction3DDescriptor} is an {@link OperationDescriptor}
 * describing the <em>imagefunction</em> operation for the collection mode.
 * This operation generates a collection of images based on a
 * {@link ImageFunction3D}.
 * <p>
 * The <em>imagefunction</em> operation takes two parameters, the image
 * function and the dimensions.
 * <p>
 * The default data type is {@link DataBuffer#TYPE_FLOAT}. The other acceptable
 * data type is {@link DataBuffer#TYPE_DOUBLE} and must be specified in a
 * {@link SampleModel} inside the {@link RenderingHints} (key is
 * {@link JAI#KEY_IMAGE_LAYOUT}).
 *
 * <table border=1>
 * <caption>Resource List</caption>
 * <tr><th>Name</th>        <th>Value</th></tr>
 * <tr><td>GlobalName</td>  <td>ImageFunction</td></tr>
 * <tr><td>LocalName</td>   <td>ImageFunction</td></tr>
 * <tr><td>Vendor</td>      <td>ca.forklabs.media.jai.opimage</td></tr>
 * <tr><td>Description</td> <td>Generates a collection of images from a functional description</td></tr>
 * <tr><td>DocURL</td>      <td>n/a</td></tr>
 * <tr><td>Version</td>     <td>$Version$</td></tr>
 * <tr><td>Arg0Desct</td>   <td>The functional description</td></tr>
 * <tr><td>Arg0Desct</td>   <td>The width of the image</td></tr>
 * <tr><td>Arg0Desct</td>   <td>The height of the image</td></tr>
 * <tr><td>Arg0Desct</td>   <td>The depth of the image</td></tr>
 * </table>
 *
 * <table border=1>
 * <caption>Parameter List</caption>
 * <tr><th>Name</th>       <th>Class Type</th>                <th>Default Value</th></tr>
 * <tr><td>function</td>   <td>{@link ImageFunction3D}</td>   <td>NO_PARAMETER_DEFAULT</td>
 * <tr><td>width</td>      <td>{@link Integer}</td>           <td>NO_PARAMETER_DEFAULT</td>
 * <tr><td>height</td>     <td>{@link Integer}</td>           <td>NO_PARAMETER_DEFAULT</td>
 * <tr><td>depth</td>      <td>{@link Integer}</td>           <td>NO_PARAMETER_DEFAULT</td>
 * </table>
 *
 * @author   <a href="mailto:forklabs at gmail.com?subject=ca.forklabs.media.jai.operator.ImageFunction3DDescriptor">Daniel Léonard</a>
 * @version $Revision$
 */
public class ImageFunction3DDescriptor extends OperationDescriptorImpl {

//---------------------------
// Class variables
//---------------------------

   /** <em>serialVersionUID</em>. */
   private static final long serialVersionUID = -2567683936057065923L;

   /** The name of this operator. */
   public static final String NAME = "ImageFunction"; //$NON-NLS-1$

   /** The name of the function parameter. */
   public static final String FUNCTION_PARAMETER_NAME = "function"; //$NON-NLS-1$
   /** The name of the width parameter. */
   public static final String WIDTH_PARAMETER_NAME = "width"; //$NON-NLS-1$
   /** The name of the height parameter. */
   public static final String HEIGHT_PARAMETER_NAME = "height"; //$NON-NLS-1$
   /** The name of the depth parameter. */
   public static final String DEPTH_PARAMETER_NAME = "depth"; //$NON-NLS-1$

   /** The index in the parameter block of the function parameter. */
   public static final int FUNCTION_PARAMETER_INDEX = 0;
   /** The index in the parameter block of the width parameter. */
   public static final int WIDTH_PARAMETER_INDEX = 1;
   /** The index in the parameter block of the height parameter. */
   public static final int HEIGHT_PARAMETER_INDEX = 2;
   /** The index in the parameter block of the depth parameter. */
   public static final int DEPTH_PARAMETER_INDEX = 3;

   /** The function default value. */
   public static final Object FUNCTION_DEFAULT_VALUE = OperationDescriptor.NO_PARAMETER_DEFAULT;
   /** The width default value. */
   public static final Object WIDTH_DEFAULT_VALUE = OperationDescriptor.NO_PARAMETER_DEFAULT;
   /** The height default value. */
   public static final Object HEIGHT_DEFAULT_VALUE = OperationDescriptor.NO_PARAMETER_DEFAULT;
   /** The depth default value. */
   public static final Object DEPTH_DEFAULT_VALUE = OperationDescriptor.NO_PARAMETER_DEFAULT;

   /** The function default value. */
   public static final Object FUNCTION_VALID_VALUE = null;
   /** The width default value. */
   public static final Object WIDTH_VALID_VALUE = new Range(Integer.class, Integer.valueOf(1), Integer.valueOf(Integer.MAX_VALUE));
   /** The height default value. */
   public static final Object HEIGHT_VALID_VALUE = new Range(Integer.class, Integer.valueOf(1), Integer.valueOf(Integer.MAX_VALUE));
   /** The depth default value. */
   public static final Object DEPTH_VALID_VALUE = new Range(Integer.class, Integer.valueOf(1), Integer.valueOf(Integer.MAX_VALUE));


   /**
    * The resource strings that provide the general documentation and specify
    * the parameter list for this operation.
    */
   private static final String[][] RESOURCES =
   {
      { "GlobalName",  ImageFunction3DDescriptor.NAME, }, //$NON-NLS-1$
      { "LocalName",   ImageFunction3DDescriptor.NAME, }, //$NON-NLS-1$
      { "Vendor",      "ca.forklabs.media.jai.opimage", }, //$NON-NLS-1$ //$NON-NLS-2$
      { "Description", ImageFunction3DDescriptor.getDescription(), }, //$NON-NLS-1$
      { "DocURL",      "n/a", }, //$NON-NLS-1$ //$NON-NLS-2$
      { "Version",     "$Version$", }, //$NON-NLS-1$ //$NON-NLS-2$
      { "arg0Desc",    ImageFunction3DDescriptor.getArg0Description(), }, //$NON-NLS-1$
      { "arg1Desc",    ImageFunction3DDescriptor.getArg1Description(), }, //$NON-NLS-1$
      { "arg2Desc",    ImageFunction3DDescriptor.getArg2Description(), }, //$NON-NLS-1$
      { "arg3Desc",    ImageFunction3DDescriptor.getArg3Description(), }, //$NON-NLS-1$
   };

   /** The supported modes. */
   private static final String[] SUPPORTED_MODES =
   {
      CollectionRegistryMode.MODE_NAME,
   };

   /** The parameter class list for this operation. */
   private static final Class<?>[] PARAMETER_CLASSES =
   {
       ImageFunction3D.class,
       Integer.class,
       Integer.class,
       Integer.class,
   };

   /** The parameter name list for this operation. */
   private static final String[] PARAMETER_NAMES =
   {
      ImageFunction3DDescriptor.FUNCTION_PARAMETER_NAME,
      ImageFunction3DDescriptor.WIDTH_PARAMETER_NAME,
      ImageFunction3DDescriptor.HEIGHT_PARAMETER_NAME,
      ImageFunction3DDescriptor.DEPTH_PARAMETER_NAME,
   };

   /** The default parameters. */
   private static final Object[] PARAMETER_DEFAULTS = new Object[]
   {
      ImageFunction3DDescriptor.FUNCTION_DEFAULT_VALUE,
      ImageFunction3DDescriptor.WIDTH_DEFAULT_VALUE,
      ImageFunction3DDescriptor.HEIGHT_DEFAULT_VALUE,
      ImageFunction3DDescriptor.DEPTH_DEFAULT_VALUE,
   };

   /** Valid parameter values. */
   private static final Object[] VALID_PARAMETERS = new Object[]
   {
      ImageFunction3DDescriptor.FUNCTION_VALID_VALUE,
      ImageFunction3DDescriptor.WIDTH_VALID_VALUE,
      ImageFunction3DDescriptor.HEIGHT_VALID_VALUE,
      ImageFunction3DDescriptor.DEPTH_VALID_VALUE,
   };


//---------------------------
// Constructor
//---------------------------

   /**
    * Constructor.
    */
   public ImageFunction3DDescriptor() {
      super(RESOURCES, SUPPORTED_MODES, 0, PARAMETER_NAMES, PARAMETER_CLASSES, PARAMETER_DEFAULTS, VALID_PARAMETERS);
      }


//---------------------------
// Class methods
//---------------------------

   /**
    * Creates and fills a new parameter block for the collection mode.
    * @param   function   the functional description.
    * @param   width   the width of the image.
    * @param   height   the height of the image.
    * @param   depth   the depth of the image.
    * @return   a new parameter block.
    */
   public static ParameterBlockJAI createParameterBlock(ImageFunction3D function, int width, int height, int depth) {
      String name = ImageFunction3DDescriptor.NAME;
      String mode = CollectionRegistryMode.MODE_NAME;
      ParameterBlockJAI pb = new ParameterBlockJAI(name, mode);
      pb.setParameter(ImageFunction3DDescriptor.FUNCTION_PARAMETER_NAME, function);
      pb.setParameter(ImageFunction3DDescriptor.WIDTH_PARAMETER_NAME, width);
      pb.setParameter(ImageFunction3DDescriptor.HEIGHT_PARAMETER_NAME, height);
      pb.setParameter(ImageFunction3DDescriptor.DEPTH_PARAMETER_NAME, depth);
      return pb;
      }

   /**
    * Performs the <em>imagefunction3d</em> operation on with the given
    * functional description.
    * @param   function   the functional description.
    * @param   width   the width of the image.
    * @param   height   the height of the image.
    * @param   depth   the depth of the image.
    * @param   hints    the rendering hints, may be {@code null}.
    * @return   the rendered result image.
    */
   @SuppressWarnings("unchecked")
   public static Collection<RenderedImage> createCollection(ImageFunction3D function, int width, int height, int depth, RenderingHints hints) {
      String name = ImageFunction3DDescriptor.NAME;
      ParameterBlockJAI pb = ImageFunction3DDescriptor.createParameterBlock(function, width, height, depth);
      Collection<RenderedImage> sinks = JAI.createCollection(name, pb, hints);
      return sinks;
      }


//---------------------------
// External resources methods
//---------------------------

   /**
    * Gets the description of this operation.
    * @return   the description message.
    */
   protected static String getDescription() {
      String key = Resources.IMAGE_FUNCTION_3D_DESCRIPTION;
      String message = Resources.getLocalizedString(key);
      return message;
      }

   /**
    * Gets the description for the first argument, the function.
    * @return   the description message.
    */
   protected static String getArg0Description() {
      String key = Resources.IMAGE_FUNCTION_3D_ARG0_DESCRIPTION;
      String message = Resources.getLocalizedString(key);
      return message;
      }

   /**
    * Gets the description for the second argument, the width.
    * @return   the description message.
    */
   protected static String getArg1Description() {
      String key = Resources.IMAGE_FUNCTION_3D_ARG1_DESCRIPTION;
      String message = Resources.getLocalizedString(key);
      return message;
      }

   /**
    * Gets the description for the third argument, the height.
    * @return   the description message.
    */
   protected static String getArg2Description() {
      String key = Resources.IMAGE_FUNCTION_3D_ARG2_DESCRIPTION;
      String message = Resources.getLocalizedString(key);
      return message;
      }

   /**
    * Gets the description for the fourth argument, the depth.
    * @return   the description message.
    */
   protected static String getArg3Description() {
      String key = Resources.IMAGE_FUNCTION_3D_ARG3_DESCRIPTION;
      String message = Resources.getLocalizedString(key);
      return message;
      }

   }
